package com.ruyuan.payment.notify.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruyuan.payment.server.service.NotifyService;
import com.ruyuan.payment.server.service.PaySuccessService;
import com.ruyuan.payment.server.wxpay.WxPayProperties;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.util.Date;

@RestController
public class WxPayController {

    private static final Logger LOG = LoggerFactory.getLogger(WxPayController.class);

    @Resource
    private NotifyService notifyService;

    @Resource
    private WxPayProperties wxPayProperties;

    @Resource
    private PaySuccessService paySuccessService;

    @PostMapping(value = "/wxpay")
    public String wxPayCallback(HttpServletRequest request, @RequestBody String body) throws Exception {
        // 文档：https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/zsgxguide.shtml
        // 我们在所有API应答和回调的HTTP头部Wechatpay-Serial，声明了此次签名所对应的平台证书的序列号
        String wechatPaySerial = request.getHeader("Wechatpay-Serial"); // 平台证书序列号
        String nonce = request.getHeader("Wechatpay-Nonce"); // 请求头Wechatpay-Nonce
        String timestamp = request.getHeader("Wechatpay-Timestamp");// 请求头Wechatpay-Timestamp
        String signature = request.getHeader("Wechatpay-Signature");// 请求头Wechatpay-Signature

        // 示例：私钥为String字符串
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
                new ByteArrayInputStream(wxPayProperties.getMerchantPrivateKey().getBytes("utf-8")));

        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(wxPayProperties.getMerchantId(), new WechatPay2Credentials(wxPayProperties.getMerchantId(),
                new PrivateKeySigner(wxPayProperties.getMerchantSerialNumber(), merchantPrivateKey)), wxPayProperties.getApiV3Key().getBytes(StandardCharsets.UTF_8));
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息

        // 从证书管理器中获取verifier
        Verifier verifier = certificatesManager.getVerifier(wxPayProperties.getMerchantId());


        // 构建request，传入必要参数
        NotificationRequest notificationRequest = new NotificationRequest.Builder()
                .withSerialNumber(wechatPaySerial)
                .withNonce(nonce)
                .withTimestamp(timestamp)
                .withSignature(signature)
                .withBody(body)
                .build();
        NotificationHandler handler = new NotificationHandler(verifier, wxPayProperties.getApiV3Key().getBytes(StandardCharsets.UTF_8));
        // 验签和解析请求体
        Notification notification = handler.parse(notificationRequest);
        //微信异步通知解析结果：Notification{id='25ea9844-f1da-53bc-b23a-26161dbf59d5', createTime='2022-05-03T09:15:08+08:00', eventType='TRANSACTION.SUCCESS', resourceType='encrypt-resource', decryptData='{"mchid":"1618056045","appid":"wx574366fd72e89541","out_trade_no":"20220503091418133653","transaction_id":"4200001500202205036176841988","trade_type":"NATIVE","trade_state":"SUCCESS","trade_state_desc":"支付成功","bank_type":"OTHERS","attach":"","success_time":"2022-05-03T09:15:08+08:00","payer":{"openid":"okNeD58On1Tgy1rQ0UniYSrAtEmE"},"amount":{"total":20,"payer_total":20,"currency":"CNY","payer_currency":"CNY"}}', summary='支付成功', resource=Resource{algorithm='AEAD_AES_256_GCM', ciphertext='yY/x9Wf7ChG+4PFhUk0nWnWjIpdM+1nZrLf9/pj1Sxvxy8jmGI4knjQirtf3ADKa598NFc77suoP0Y+m0gsQQHLm+ZODTYJ0wuqCU8cD1fIL+4xIzfibHbjPVz2Rh/Pl65rFgwrFAmfwcyoDFyCuji9rYjm1Wg7Ar4h0QOQyzT+DTKKC2K6OSn1Z/MuBMfPFajLbv2mIod+Z2vlgSVBSz19YZAb0/GikXWu13CDN1fnDHVWypihAxyd9dsHDbIyvyh9luCGFTX+XXkTAZOhjBJfGkR3175APUFh1lj6Hpmj3mvCqWfDfGcQZMAYdXQkbMWadw8cZbAWnWW6EbhPWMFhywwwsKW7LU4Yw/1TjhM57JEZWbkgw+eClf9+d778ODkqoYA6nMSnt59PhFKbyJtBmsx5kLNkaEfEB4xqr62NCmaZoI3HCANczTZtIKmbAiLtfUx0FEaoeXEikbrpJTcvtwIytLXYmicFqUemIKOuMhRrbMZqyLG9SR9wi1GEtIPku65WjXIzdaxcSUEGScNVPWR+r+vUpf6p8Ll5jmZuS6ZxjdSz8e9+7CY/q6QEpIyKGzmZO', associatedData='transaction', nonce='fKcU2Z7fjEbC', originalType='transaction'}}
        LOG.info("微信异步通知解析结果：{}", notification.toString());
        String decryptData = notification.getDecryptData();
        JSONObject dataJson = JSON.parseObject(decryptData);
        String outTradeNo = dataJson.getString("out_trade_no");
        String tradeState = dataJson.getString("trade_state"); // "SUCCESS"
        Date channelTime = dataJson.getDate("success_time");
        if ("SUCCESS".equals(tradeState)) {
            paySuccessService.afterPaySuccess(outTradeNo, channelTime);
        }
        return "success";
    }
}
